package com.edu.app.controller.core;

import com.alibaba.fastjson.JSON;
import com.edu.app.bean.core.SysRole;
import com.edu.app.bean.core.SysUser;
import com.edu.app.bean.core.popup.UsersPop;
import com.edu.app.bean.linkbeans.SysUserRole;
import com.edu.app.constant.ErrorConstant;
import com.edu.app.constant.StaticConstant;
import com.edu.app.constant.SysMessage;
import com.edu.app.model.UserModel;
import com.edu.app.service.sys.core.SysUserService;
import com.edu.app.service.sys.linkservices.SysUserActivityService;
import com.edu.app.service.sys.linkservices.SysUserCustomerService;
import com.edu.app.service.sys.linkservices.SysUserRoleService;
import com.edu.app.service.sys.security.SysSecurityService;
import com.edu.app.util.*;

import com.github.pagehelper.PageInfo;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;

import java.util.Date;
import java.util.List;

@RequestMapping(value = "/api/users")
@RestController
public class SysUserController {

    @Autowired
    private SysUserService sysUserService;

    @Autowired
    private SysUserRoleService sysUserRoleService;

    @Autowired
    private SysUserActivityService sysUserActivityService;

    @Autowired
    private SysUserCustomerService sysUserCustomerService;

    @Autowired
    private SysSecurityService sysSecurityService;

    /*
     * 查询User列表
     * http://localhost:8080/api/users
     * */
    @GetMapping(value = "")
    @RequiresAuthentication
    //@RequiresRoles(value = {StaticConstant.ADMIN_ROLE})
    public ModelMap getUserList (){
        try{
            List<SysUser> userList = sysUserService.getObjectList();
            return MsgUtil.retMsg(SysMessage.GET_USERLIST_SUCCEED, "user_list", userList);
        }catch (Exception e){
            return ErrorUtil.retErrMsg(ErrorConstant.SERVER_INTERNAL_ERROR);
        }
    }

    @GetMapping(value = "/getUserListByType")
    @RequiresAuthentication
    //@RequiresRoles(value = {StaticConstant.ADMIN_ROLE})
    public ModelMap getUserListByType(@RequestParam("roleName") String roleName, @RequestParam("status") Integer status){
        try{
            List<SysUser> userList = sysUserService.getUserListByType(roleName, status);
            return MsgUtil.retMsg(SysMessage.GET_USERLIST_SUCCEED, "user_list", userList);
        }catch (Exception e){
            return ErrorUtil.retErrMsg(ErrorConstant.SERVER_INTERNAL_ERROR);
        }
    }

    @GetMapping(value = "/users_pop")
    @RequiresAuthentication
    //@RequiresRoles(value = {StaticConstant.ADMIN_ROLE})
    public ModelMap getUsersPop (){
        try{
            List<UsersPop> usersPop = sysUserService.getUsersPop();
            return MsgUtil.retMsg(SysMessage.GET_USERLIST_SUCCEED, "pop_list", usersPop);
        }catch (Exception e){
            return ErrorUtil.retErrMsg(ErrorConstant.SERVER_INTERNAL_ERROR);
        }
    }

    @GetMapping(value = "/users_pop/getByName")
    @RequiresAuthentication
    //@RequiresRoles(value = {StaticConstant.ADMIN_ROLE})
    public ModelMap getUsersPopByName (@RequestParam("name") String name){
        try{
            List<UsersPop> usersPop = sysUserService.getUsersPopByName(name);
            return MsgUtil.retMsg(SysMessage.GET_USERLIST_SUCCEED, "pop_list", usersPop);
        }catch (Exception e){
            return ErrorUtil.retErrMsg(ErrorConstant.SERVER_INTERNAL_ERROR);
        }
    }

    /*
     * 按照id查询User
     * 链接测试
     * http://localhost:8080/api/users/1
     * */
    @GetMapping(value = "/{id}")
    @RequiresAuthentication
    public ModelMap getSysUserById (@PathVariable Integer id){
        ModelMap map = new ModelMap();
        try{
            SysUser user = sysUserService.getObjectById(id);
            return MsgUtil.retMsg(SysMessage.GET_USER_SUCCEED, "user", user);
        }catch (Exception e){
            return ErrorUtil.retErrMsg(ErrorConstant.SERVER_INTERNAL_ERROR);
        }
    }

    /*
    * 按Page分页查询列表
    * 测试链接
    * http://localhost:8080/api/users/pages?offset=1&limit=2
    * */
    @GetMapping("/pages")
    //@RequiresRoles(value = {StaticConstant.ADMIN_ROLE})
    public ModelMap getUserByPage(@RequestParam Integer offset, @RequestParam Integer limit) {

        try {
            PageInfo pageInfo = sysUserService.findItemByPage(offset, limit);
            return MsgUtil.retMsg(SysMessage.GET_USER_BY_PAGE_SUCCEED, "page_info", pageInfo);
        } catch (Exception e) {
            return ErrorUtil.retErrMsg(ErrorConstant.SERVER_INTERNAL_ERROR);
        }
    }

    @PostMapping("")
    @Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,timeout=36000,rollbackFor=Exception.class)
    //@RequiresRoles(value = {StaticConstant.ADMIN_ROLE})
    public ModelMap addUser (@RequestHeader("Authorization") String token, @RequestBody SysUser user, @RequestParam String roleList){

        try{
            String username = JWTUtil.getUsername(token);
            user.initializeSystemColumns(username);

            Integer d = sysUserService.add(user);
            if(d > 0 ){
                List<SysRole> sysRoleList = JSON.parseArray(roleList, SysRole.class);
                for(int i=0; i<sysRoleList.size(); i++){
                    sysUserRoleService.add(new SysUserRole(user.getId(), sysRoleList.get(i).getId()));
                }
                return MsgUtil.retMsg(SysMessage.ADD_USER_SUCCEED, "user", user);
            }
            else{
                return ErrorUtil.retErrMsg(ErrorConstant.SERVER_INTERNAL_ERROR);
            }
        }catch (org.springframework.dao.DuplicateKeyException e){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return ErrorUtil.retErrMsg(ErrorConstant.USER_ALREADY_EXISTS);
        }catch (Exception e){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return ErrorUtil.retErrMsg(e);
        }
    }

    @PutMapping("")
    @RequiresRoles(value = {StaticConstant.ADMIN_ROLE})
    public ModelMap updateUser (@RequestHeader("Authorization") String token, @RequestBody SysUser user){

        if(user.getId() == null || user.getPassword() == null || user.getUsername() == null) {
            return ErrorUtil.retErrMsg(ErrorConstant.SERVER_INTERNAL_ERROR);
        }

        String username = JWTUtil.getUsername(token);

        //别忘了加密新密码
        if(user.getPassword() != null){
            user.setPassword(SecurityUtil.getEncryptCode(user.getPassword(),user.getUsername()));
        }

        user.initializeSystemColumns(username);

        Integer i = sysUserService.update(user);
        if(i > 0 ){
            return MsgUtil.retMsg(SysMessage.UPDATE_USER_SUCCEED, null, null);
        }
        else{
            return ErrorUtil.retErrMsg(ErrorConstant.SERVER_INTERNAL_ERROR);
        }
    }

    /*@PatchMapping(value = "/{id}")
    @RequiresRoles(value = {StaticConstant.ADMIN_ROLE})
    public ModelMap patchUser (@PathVariable Integer id, @RequestBody SysUser user){

        SysUser dbUser = sysUserService.getObjectById(id);
        Boolean isPwdChanged = false;

        //如果password不相等，则更新password
        if(!dbUser.getPassword().equalsIgnoreCase(SecurityUtil.getEncryptCode(user.getPassword(),user.getUsername()))){
            isPwdChanged = true;
        }

        BeanUtils.copyProperties(user, dbUser, CommonUtils.getNullPropertyNames(user));
        if(isPwdChanged){
            dbUser.setPassword(SecurityUtil.getEncryptCode(user.getPassword(),user.getUsername()));
        }
        Integer i = sysUserService.update(dbUser);
        if(i > 0 ){
            return MsgUtil.retMsg(SysMessage.PATCH_USER_SUCCEED, null, null);
        }
        else{
            return ErrorUtil.retErrMsg(ErrorConstant.SERVER_INTERNAL_ERROR);
        }
    }*/

    @PatchMapping(value = "")
    @RequiresAuthentication
    public ModelMap patchUser (@RequestHeader("Authorization") String token, @RequestBody SysUser user, @RequestParam Boolean isCheckPwd){

        SysUser dbUser = sysUserService.getObjectById(user.getId());
        Boolean isPwdChanged = false;

        //如果password不相等，则更新password
        if(isCheckPwd && !dbUser.getPassword().equals(user.getPassword())){
            isPwdChanged = true;
        }

        BeanUtils.copyProperties(user, dbUser, CommonUtils.getNullPropertyNames(user));
        if(isPwdChanged){
            dbUser.setPassword(SecurityUtil.getEncryptCode(user.getPassword(),user.getUsername()));
        }
        Integer i = sysUserService.update(dbUser);
        UserModel userModel = sysUserService.getUserModelById(dbUser.getId());
        if(i > 0 ){
            return MsgUtil.retMsg(SysMessage.PATCH_USER_SUCCEED, "user_model", userModel);
        }
        else{
            return ErrorUtil.retErrMsg(ErrorConstant.SERVER_INTERNAL_ERROR);
        }
    }

    /*
     * 删除User
     * */
    @DeleteMapping("")
    @Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,timeout=36000,rollbackFor=Exception.class)
    //@RequiresRoles(value = {StaticConstant.ADMIN_ROLE})
    public ModelMap deleteUser (@RequestParam Integer id){

        try{
            //Before deleting user, make sure to clear up all necessary related items
            sysUserCustomerService.deleteUserCustomerByUserId(id);
            sysUserActivityService.deleteUserActivityByUserId(id);
            sysUserRoleService.deleteUserRoleByUserId(id);
            sysUserService.delete(id);
            return MsgUtil.retMsg(SysMessage.DELETE_USER_SUCCEED, "id", id);
        }catch (Exception e){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return ErrorUtil.retErrMsg(e);
        }

    }

    @PostMapping("/chgpwd")
    @RequiresAuthentication
    public ModelMap chgpwd (@RequestParam String username, @RequestParam String oldPwd, @RequestParam String newPwd, @RequestHeader("Authorization") String token){

        String currentUserName = JWTUtil.getUsername(token);
        SysUser currentUser = sysUserService.getUserByName(currentUserName);
        List<SysRole> currentRoleList = sysUserRoleService.getRoleListByUserId(currentUser.getId());

        if(currentUserName.equalsIgnoreCase(username)){
            if(!currentUser.getPassword().equals(SecurityUtil.getEncryptCode(oldPwd,username))){
                return ErrorUtil.retErrMsg(ErrorConstant.OLD_PWD_ERROR);
            }
            currentUser.setPassword(SecurityUtil.getEncryptCode(newPwd,username));
            Integer i = sysUserService.update(currentUser);
            if(i > 0 ){
                return MsgUtil.retMsg(SysMessage.CHANGE_USER_PASSWORD_SUCCEED, null, null);
            }
            else{
                return ErrorUtil.retErrMsg(ErrorConstant.SERVER_INTERNAL_ERROR);
            }
        }else if(currentRoleList.contains(StaticConstant.ADMIN_ROLE)){
            SysUser targetUser = sysUserService.getUserByName(username);
            if(targetUser != null){
                targetUser.setUpdate_by(currentUserName);
                targetUser.setUpdate_time(new Date());
                Integer i = sysUserService.update(currentUser);
                if(i > 0 ){
                    return MsgUtil.retMsg(SysMessage.CHANGE_USER_PASSWORD_SUCCEED, null, null);
                }
                else{
                    return ErrorUtil.retErrMsg(ErrorConstant.SERVER_INTERNAL_ERROR);
                }
            }else{
                return ErrorUtil.retErrMsg(ErrorConstant.USER_NOT_EXISTS);
            }
        }else{
            return ErrorUtil.retErrMsg(ErrorConstant.CHANGE_PASSWORD_NOT_SAME_USER);
        }
    }

    @PostMapping("/renewpwd")
    @RequiresRoles(value = {StaticConstant.ADMIN_ROLE})
    public ModelMap renewpwd (@RequestParam String username, @RequestParam String newpassword, @RequestParam String code, @RequestParam String hashcode){

        //校验验证码的合法性
        if(!sysSecurityService.validateVerifyCode(code, hashcode, username)){
            return ErrorUtil.retErrMsg(ErrorConstant.INVALID_VERIFICATION);
        }

        SysUser sysUser = sysUserService.getUserByName(username);

        if(sysUser != null){
            sysUser.setPassword(SecurityUtil.getEncryptCode(newpassword,username));
            Integer i = sysUserService.update(sysUser);

            if(i > 0 ){
                return MsgUtil.retMsg(SysMessage.CHANGE_USER_PASSWORD_SUCCEED, null, null);
            }
            else{
                return ErrorUtil.retErrMsg(ErrorConstant.SERVER_INTERNAL_ERROR);
            }
        }else{
            return ErrorUtil.retErrMsg(ErrorConstant.SERVER_INTERNAL_ERROR);
        }
    }

    @GetMapping(value = "/getUserModel")
    @RequiresAuthentication
    public ModelMap getUserModel(@RequestParam Integer id){

        try{
            UserModel userModel = sysUserService.getUserModelById(id);
            return MsgUtil.retMsg(SysMessage.GET_USER_MODEL_SUCCEED, "user_model", userModel);
        }catch (Exception e){
            return ErrorUtil.retErrMsg(e);
        }
    }

    @PatchMapping(value = "/updateUserModel")
    @RequiresRoles(value = {StaticConstant.ADMIN_ROLE})
    @Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,timeout=36000,rollbackFor=Exception.class)
    public ModelMap updateUserModel(@RequestHeader("Authorization") String token, @RequestBody SysUser user, @RequestParam String roleList){

        try{
            String username = JWTUtil.getUsername(token);
            user.initializeUpdateSystemColumns(username);

            SysUser dbUser = sysUserService.getObjectById(user.getId());
            Boolean isPwdChanged = false;

            //如果password不相等，则更新password
            if(!dbUser.getPassword().equals(user.getPassword())){
                isPwdChanged = true;
            }

            BeanUtils.copyProperties(user, dbUser, CommonUtils.getNullPropertyNames(user));
            if(isPwdChanged){
                dbUser.setPassword(SecurityUtil.getEncryptCode(user.getPassword(),user.getUsername()));
            }

            sysUserService.update(dbUser);
            //remove the old relationships
            sysUserRoleService.deleteUserRoleByUserId(dbUser.getId());

            //update the new relationships
            List<SysRole> sysRoleList = JSON.parseArray(roleList, SysRole.class);
            for(int i=0; i<sysRoleList.size(); i++){
                sysUserRoleService.add(new SysUserRole(user.getId(), sysRoleList.get(i).getId()));
            }

            return MsgUtil.retMsg(SysMessage.UPDATE_USER_MODEL_SUCCEED, null, null);
        }catch (Exception e){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return ErrorUtil.retErrMsg(e);
        }
    }
}
